package com.colabo.j2ee.web.oaf.security.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.colabo.j2ee.web.core.service.impl.DefaultServiceImpl;

public class UrlSecurityMetadataSourceDefiner extends DefaultServiceImpl
		implements FilterInvocationSecurityMetadataSource {

	/**
	 * 配置参数：公共资源配置，元素为公共访问页面的url
	 */
	private Collection<String> publicSource;
	
	public Collection<String> getPublicSource() {
		return publicSource;
	}

	public void setPublicSource(Collection<String> publicSource) {
		this.publicSource = publicSource;
	}
	
	/**
	 * 判定一个url是否是预设定的公共url
	 * @param url 待判定url
	 * @return true 是公共url； false 相反
	 */
	private boolean isPublicSource(String url) {
		for (String publicUrl : publicSource) {
			if (url.endsWith(publicUrl.trim())) {
				return Boolean.TRUE;
			}
		}
		return Boolean.FALSE;
	}
	
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return new ArrayList<ConfigAttribute>();
	}

	/**
	 * 
	 */
	public Collection<ConfigAttribute> getAttributes(Object arg0)
			throws IllegalArgumentException {
		FilterInvocation invocation = (FilterInvocation) arg0;
		// 将url的参数去掉，以判断是否属于公共资源
		// FIXME: 此处仅考虑了使用“？”带参数的情形，没有考虑 “#” 带锚点的情形
		String url = invocation.getRequestUrl();
		if (url.lastIndexOf('?') > -1) {
			url = url.substring(0, url.lastIndexOf('?'));
		}
		if (isPublicSource(url)) {
			return null;
		}
		
		/**
		 *  循环的将url的父路径加入confDef对象中
		 *  如： jsp/module1/add.jsp 则将
		 *   jsp
		 *   jsp/module1
		 *   两条url加入控制定义对象中
		 */
		Collection<ConfigAttribute>	confDef = new Vector<ConfigAttribute>();
		while (url.length() > 0) {
			confDef.add(new SecurityConfig(url));
			if (url.lastIndexOf('/') > -1) {
				url = url.substring(0, url.lastIndexOf('/'));
			} else {
				url = "";
			}
		}
		
		HttpServletRequest req = invocation.getHttpRequest();
		Map parameterMap = req.getParameterMap();
		for (Iterator<Entry> it = parameterMap.entrySet().iterator(); it.hasNext();) {
			String key = (String) it.next().getKey();
			confDef.add(new SecurityConfig(key + "=" + parameterMap.get(key)));
		}
		
		return confDef;
	}

	public boolean supports(Class<?> arg0) {
		return arg0.isAssignableFrom(FilterInvocation.class);
	}

}
